!function(root,fn){
	if (typeof exports === 'object') {
        // Node.
        module.exports = fn.call(root);
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function(){ return fn.call(root) });
    } else {
        // Browser globals (root is window)
        root.diqye = fn.call(root);
    }
}(this,function(){
/*=======================*/
//数据类型判断
var TYPE=(function(){
	var r={},types=['Arguments','Function','String','Number','Date','RegExp','Error','Null'];
	for(var i=0,t;t=types[i++];){
		!function(t){
			r['is'+t]=function(obj){
				return Object.prototype.toString.call(obj) === '[object '+t+']';
			}
		}(t)
	}
	return r;
})();
/*=======================*/
//前端路由 本来打算写成一个函数，但路由对象只需要全局存在一个即可 并没有发现需要多个对象存在的场景
var route=(function(){
	var p={
		intes:[]
	};
	function getPath(url){
		var path=url.split("#")[1];
		if(!path)return "/";
		if(path.charAt(0)!="/")path="/"+path;
		return path;
	}
	function use(fn){
		p.intes.push(fn);
	}
	function hashchange(path){
		var req={path:path},hlen=p.intes.length;
		if(hlen==0){
			doother(req);
			return;
		}
		//执行拦截器链
		!function intec(i){
			if(i==hlen){
				return;
			}
			p.intes[i](req,function(){
				intec(i+1);
			});
		}(0);
	}
	function to(path){
		window.location.hash=path;
	}
	function start(){
		window.onhashchange=function(){
			var path=getPath(location.href);
			hashchange(path);
		}
		var path=getPath(location.href);
		hashchange(path);
	}
	var result={
		start:start,
		use:use,
		to:to,
		mix:mix
	}
	//扩展API
	function mix(obj){
		for(var key in obj){
			result[key]=obj[key];
		}
	}
	return result;
})();
/*=======================*/
//get 路由实现
!function(mix){
	//获取处理后的path  去掉问好 和多余的/
	function pathfn(path){
		var a=path.split('?');
		if(a[1])path=a[0];
		path=path.split('//').join('/');
		return path;
	}
	//function interceptor
	function get1(fn,cb){
		return function(req,next){
			if(fn(pathfn(req.path)))cb(req,next);
			else next();
		}
	}
	//regExp interceptor
	function get2(reg,cb){
		return function(req,next){
			var para=reg.exec(pathfn(req.path));
			if(para){
				req.para=para;
				cb(req,next);
			}else next();
		}
	}
	//:xxx  xxx是可以扩展的
	function get3(ps,cb){
		var reg=get.type[ps[1]];
		return function(req,next){
			var path=pathfn(req.path);
			var para=path.substr(ps[0].length);
			if(pathfn(req.path).indexOf(ps[0])==0&&reg.test(para)){
				req.para=para;
				cb(req,next);
			}else next();
		}
	}
	//通配符  /xxxx*  *后面不允许有字符
	function get4(os,cb){
		return function(req,next){
			if(pathfn(req.path).indexOf(os[0])==0)cb(req,next);
			else next();
		}
	}
	//string interceptor
	function get5(path,cb){
		return function(req,next){
			if(path==pathfn(req.path))cb(req,next);
			else next();
		}
	}
	function get(path,cb){
		//匹配路径支持的5中情况
		if(TYPE.isFunction(path))this.use(get1(path,cb));
		if(TYPE.isRegExp(path))this.use(get2(path,cb));
		if(!TYPE.isString(path))return;
		var a=path.split(':');
		if(a.length!=1){
			this.use(get3(a,cb));
			return;
		}
		var b=path.split('*');
		if(b.length!=1){
			this.use(get4(b,cb));
			return;
		}
		this.use(get5(path,cb));
	}
	get.type={
		'number':/^\d+$/,
		'string':/^[^\/]+$/,
		'date':/^[0-9]{6,6}$/
	};
	mix({
		get:get
	});
}(route.mix);
/*=======================*/
//编码问题
!function(use){
	use(function(req,next){
		var path=window.decodeURI(req.path);
		req.path=path;
		next();
	});
}(route.use);
/*=======================*/
function each(arr,fn){
	for(var i=0,l=arr.length,t;i<l;i++){
		t=arr[i];
		if(fn(t,i)===false)break;
	}
}
//url参数和json互相转换 转换后存储在req.query属性中
!function(route){
	var to=route.to,use=route.use;
	
	function stringify(obj){
		var a=[];
		for(key in obj){
			a.push(key+'='+obj[key]);
		}
		return a.join('&')
	}
	use(function(req,next){
		req.query={};
		var urlp=req.path.split('?')[1];
		if(!urlp){
			next();
			return;
		}
		var a=urlp.split('&');
		var r={};
		each(a,function(t,i){
			var b=t.split('=');
			r[b[0]]=b[1];
		});
		req.query=r;
		next();
	});
	route.mix({
		to:function(path,obj){
			if(path.indexOf('?')==-1&&obj){
				path+='?'+stringify(obj);
			}
			to(window.encodeURI(path));
		}
	})
}(route);
/*=======================*/
	return {
        type:TYPE,
        route:route
    }
});